/* Copyright 2010 Michael Wenders, michaelwenders <at> gmx <dot> de

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef LIBLCM_H_
#define LIBLCM_H_

#include <string>
#include <vector>
#include <mysql/mysql.h>
#include <time.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
using namespace std;

#define LIBLCM_MAIN_VERSION "0"
#define LIBLCM_SUB_VERSION "5"
#define LIBLCM_PATCHLEVEL_VERSION "1"
#define LIBLCM_VERSION LIBLCM_MAIN_VERSION "." LIBLCM_SUB_VERSION "." LIBLCM_PATCHLEVEL_VERSION

namespace lcm
{
	namespace error
	{
		// 100 - 149: command line parsing
		const int CMDLINE_MESSED_UP 				= 0101;
		const int CMDLINE_BREAK 					= 0102;
		const int CMDLINE_MISSING_OPTION			= 0103;
		const int CMDLINE_PATH_MISSING				= 0104;
		const int CMDLINE_MISSING_GROUP_ARGUMENT 	= 0105;
		const int CMDLINE_MISSING_PATH_ARGUMENT 	= 0106;
		const int CMDLINE_MISSING_DESC_ARGUMENT 	= 0107;

		// 150 - 199: network
		const int NET_NO_SOCKET_CREATED				= 0151;
		const int NET_COULD_NOT_BIND				= 0152;
		const int NET_COULD_NOT_LISTEN				= 0153;
		const int NET_COULD_NOT_ACCEPT				= 0154;
		const int NET_COULD_NOT_READ				= 0155;
		const int NET_COULD_NOT_WRITE				= 0156;
		const int NET_ADDR_WRONG					= 0157;

		// 200 - 249: mysql
		const int MYSQL_CONNECT_ERROR				= 0200;
		const int MYSQL_QUERY_ERROR					= 0201;
		const int MYSQL_RESULT_ERROR				= 0202;
		const int MYSQL_INIT_ERROR					= 0203;
		const int MYSQL_ERROR_EXEC_SQL				= 0204;

		// 250 - 299: system
		const int SYSTEM_NO_LOGGER_CREATED			= 0250;
		const int SYSTEM_NO_CONFIG_CREATED			= 0251;
		const int SYSTEM_CANNOT_DAEMONIZE 			= 0252;
		const int SYSTEM_CANNOT_CREATE_LOCK_FILE 	= 0253;
		const int SYSTEM_CANNOT_SET_LOCK		 	= 0254;
		const int SYSTEM_ALREADY_RUNNING			= 0255;
		const int SYSTEM_CANNOT_CREATE_PID_FILE		= 0256;

		// 300 - 349: config file parsing
		const int CONFIG_NO_FILE_FOUND				= 0300; //-0x0300-0x0349----
		const int CONFIG_COULD_NOT_READ				= 0301; // config parsing
	}

	namespace log
	{
		/* log and verbosity levels */
		const int LOGGER_DEBUG						= 1000;
		const int LOGGER_INFO						= 1001;
		const int LOGGER_WARNING					= 1002;
		const int LOGGER_ERROR						= 1003;
		const int LOGGER_CRITICAL					= 1004;
		const int LOGGER_PANIC						= 1005;
		const int LOGGER_NONE						= 1006;

		class Logger
		{
		public:
			Logger();
			Logger(string logfile);
			Logger(string logfile,int loglevel);
			Logger(int verbosity);
			Logger(string logfile,int loglevel,int verbosity);
			~Logger();

			void setLogLevel(int loglevel);
			void setLogLevel(string loglevel);
			void setVerbosity(int verbosity);

			int write(string text, int level);

		private:
			string logfile;
			int loglevel;
			int verbosity;
			bool failed;
		};
	}

	namespace lcmp
	{
		/* lcmp definitions */
		const int LCMP_OK							= 00;	//-0-31-----------------------
		const int LCMP_DENY							= 01;	// status messages
		const int LCMP_INCOMPATIBLE					= 02;	//
		const int LCMP_HOSTUNKNOWN					= 03;	//
		const int LCMP_GREETING 					= 20;	//-32-63----------------------
		const int LCMP_LEAVE 						= 21;	//
		const int LCMP_SCRIPTNAME					= 22;	// other commands send by client
		const int LCMP_VERSION 						= 40;	//-64-91----------------------
		const int LCMP_CLIENTNAME 					= 41;	// other commands send by server
		const int LCMP_GOODBYE 						= 42;	//
		const int LCMP_SCRIPT						= 43;
	}

	typedef std::vector< std::vector<std::string> > SVEC2D;
	typedef std::vector<std::string> SVEC1D;

	const int OK = 0;
	const int NOT_OK = 1;

	/* string manipulation */
	bool doesFileExist(string dir);
	string stringToBash(string command);
	string eraseComments(string line);
	string eraseSpaces(string line);
	string eraseChars(string line,char c);
	string copyUntil(string line, char c);
	string removeUntil(string line, char c);
	string lineToLowerCase(string line);
	string getMetaOption(string line);
	string getParameter(string line);
	string getValue(string line);
	int stringToInt(string text);
	string intToString(int number);

	/* authentication */
	bool amIroot();

	/* other */
	string getDateTime();
	string getMD5(string file);

	/* network */
	int readSocket(int socket, string &text);
	int writeSocket(int socket, string text);

	namespace ssl
	{
		RSA* initSSLPubKey(string keyFile);
		RSA* initSSLPriKey(string keyFile);
		int readSSLSocket(int socket, string &text, RSA* rsa);
		int writeSSLSocket(int socket, string text, RSA* rsa);
	}
}
#endif /* LIBLCM_H_ */
